using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Northwoods.Go;

namespace Workflows.Diagrams
{
    [Serializable()]
    public class LinkLabel : GoText, IGoLinkLabel
    {
        #region members
        public const int ChangedOffset = LastChangedHint + 3214;
        public const int ChangedSegment = LastChangedHint + 3215;
        public const int ChangedSegmentPercentage = LastChangedHint + 3216;
        public const int ChangedConnectionColor = LastChangedHint + 3217;

        private SizeF myOffset = new SizeF(0, 0);
        private int mySegment = 3;
        private Single mySegmentPercentage = 50;
        private Color myConnectionColor = Color.Gray;
        #endregion

        #region ctor
        public LinkLabel()
        {
            this.Alignment = GoObject.Middle;
            this.Bordered = true;
            this.Copyable = false;
            this.Editable = true;
            this.Text = "label";
            this.TextColor = Color.DarkGreen;
            this.TransparentBackground = false;
        }
        #endregion

        #region Properties
        public GoLabeledLink LabeledLink
        {
            get
            {
                return (GoLabeledLink)this.Parent;
            }
        }

        public Color ConnectionColor
        {
            get
            {
                return myConnectionColor;
            }
            set
            {
                Color old = this.myConnectionColor;
                if (!old.Equals(value))
                {
                    this.myConnectionColor = value;
                    Changed(ChangedConnectionColor, 0, old, NullRect, 0, value, NullRect);
                }
            }
        }
        #endregion

        #region overrides
        public override void Paint(Graphics g, GoView view)
        {
            GoLabeledLink l = this.LabeledLink;
            Color c = this.ConnectionColor;
            if (l != null && (!c.Equals(Color.Empty)))
            {
                Pen pen = new Pen(c);
                PointF cp = this.LinkLabelConnnectionPoint;
                PointF center = this.Center;
                GoShape.DrawLine(g, view, pen, center.X, center.Y, cp.X, cp.Y);
                pen.Dispose();
            }
            base.Paint(g, view);
        }

        public override RectangleF ExpandPaintBounds(RectangleF rect, GoView view)
        {
            Color c = this.ConnectionColor;
            rect = base.ExpandPaintBounds(rect, view);
            if (!c.Equals(Color.Empty))
            {
                PointF cp = this.LinkLabelConnnectionPoint;
                rect = RectangleF.Union(rect, new RectangleF(cp.X, cp.Y, 1, 1));
            }
            return rect;
        }

        public override void ChangeValue(GoChangedEventArgs e, bool undo)
        {
            switch (e.SubHint)
            {
                case ChangedOffset:
                    this.Offset = e.GetSize(undo);
                    break;
                case ChangedSegment:
                    this.Segment = e.GetInt(undo);
                    break;
                case ChangedSegmentPercentage:
                    this.SegmentPercentage = e.GetFloat(undo);
                    break;
                case ChangedConnectionColor:
                    this.ConnectionColor = (Color)e.GetValue(undo);
                    break;
                default:
                    base.ChangeValue(e, undo);
                    break;
            }
        }
        #endregion

        #region IGoLinkLabel Members

        public PointF LinkLabelConnnectionPoint
        {
            get
            {
                GoLabeledLink l = this.LabeledLink;
                if (l != null && (l.RealLink != null))
                {
                    GoLink rl = l.RealLink;
                    int numpts = rl.PointsCount;
                    if (numpts < 2)
                        return this.Center;
                    int s = this.Segment;
                    if (s >= numpts - 1)
                        s = numpts - 2;
                    if (s < 0)
                        s = 0;

                    PointF a = rl.GetPoint(s);
                    PointF b = rl.GetPoint(s + 1);
                    Single segdst = this.SegmentPercentage;
                    return new PointF(a.X + ((b.X - a.X) * segdst) / 100, a.Y + ((b.Y - a.Y) * segdst) / 100);
                }
                else
                {
                    return this.Center;
                }
            }
        }

        public SizeF Offset
        {
            get
            {
                return this.myOffset;
            }
            set
            {
                SizeF old = this.myOffset;
                if (!old.Equals(value))
                {
                    this.myOffset = value;
                    this.Changed(ChangedOffset, 0, null, MakeRect(old), 0, null, MakeRect(value));
                }
            }
        }

        public int Segment
        {
            get
            {
                return this.mySegment;
            }
            set
            {
                int old = this.mySegment;
                if (old != value)
                {
                    this.mySegment = value;
                    Changed(ChangedSegment, old, null, NullRect, value, null, NullRect);
                }
            }
        }

        public float SegmentPercentage
        {
            get
            {
                return mySegmentPercentage;
            }
            set
            {
                Single old = this.mySegmentPercentage;
                if (old != value)
                {
                    this.mySegmentPercentage = value;
                    Changed(ChangedSegmentPercentage, 0, null, MakeRect(old), 0, null, MakeRect(value));
                }
            }
        }

        #endregion
    }
}
